package com.xudu.tourbackend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.xudu.tourbackend.common.PageRequest;
import com.xudu.tourbackend.common.globalEnum.ErrorCode;
import com.xudu.tourbackend.entity.*;
import com.xudu.tourbackend.entity.request.AddRouteRequest;
import com.xudu.tourbackend.entity.request.SearchRouteRequest;
import com.xudu.tourbackend.entity.request.UpdateRouteRequest;
import com.xudu.tourbackend.entity.vo.RouteVo;
import com.xudu.tourbackend.entity.vo.ScenicAreaVo;
import com.xudu.tourbackend.entity.vo.UserVo;
import com.xudu.tourbackend.exception.ServiceException;
import com.xudu.tourbackend.mapper.ElementMapper;
import com.xudu.tourbackend.mapper.RouteMapper;
import com.xudu.tourbackend.mapper.ScenicAreaMapper;
import com.xudu.tourbackend.mapper.ScenicSpotMapper;
import com.xudu.tourbackend.service.IRouteService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xudu.tourbackend.service.IUserService;
import com.xudu.tourbackend.utils.QiniuUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import static com.xudu.tourbackend.constant.RouteConstant.APPROVE;
import static com.xudu.tourbackend.constant.RouteConstant.UNAPPROVED;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author xudu
 * @since 2024-06-17
 */
@Service
@Slf4j
public class RouteServiceImpl extends ServiceImpl<RouteMapper, Route> implements IRouteService {

    @Resource
    private RouteMapper routeMapper;

    @Resource
    private IUserService userService;

    @Resource
    private ScenicAreaMapper scenicAreaMapper;

    @Resource
    private ScenicSpotMapper scenicSpotMapper;

    @Resource
    private ElementMapper elementMapper;


    @Resource
    private QiniuUtil qiniuUtil;

    @Override
    public RouteVo addRoute(AddRouteRequest addRouteRequest, HttpServletRequest request) {
        UserVo loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            log.info("用户未登录");
            return null;
        }
        Integer loginUserId = loginUser.getUserid();

        //获取请求添加的参数
        String routeName = addRouteRequest.getRouteName();
        if (StringUtils.isBlank(routeName)){
            throw new ServiceException(ErrorCode.PARAMS_ERROR, "路线名称不能为空");
        }
        String routeInfo = addRouteRequest.getRouteInfo();
        if (StringUtils.isBlank(routeInfo)){
            throw new ServiceException(ErrorCode.PARAMS_ERROR, "路线详情不能为空");
        }
        MultipartFile routeImage = addRouteRequest.getRouteImage();
        if (routeImage == null){
            throw new ServiceException(ErrorCode.PARAMS_ERROR, "路线图片不能为空");
        }
        Integer routeMileage = addRouteRequest.getRouteMileage();
        if (routeMileage == null){
            throw new ServiceException(ErrorCode.PARAMS_ERROR, "路线里程不能为空");
        }
        Integer spendTime = addRouteRequest.getSpendTime();
        if (spendTime == null){
            throw new ServiceException(ErrorCode.PARAMS_ERROR, "花费时间不能为空");
        }
        String suitableTime = addRouteRequest.getSuitableTime();
        if (StringUtils.isBlank(suitableTime)){
            throw new ServiceException(ErrorCode.PARAMS_ERROR, "适宜时间不能为空");
        }
        List<Integer> alongScenics = addRouteRequest.getAlongScenics();
        if (alongScenics.isEmpty()){
            throw new ServiceException(ErrorCode.PARAMS_ERROR, "沿途景区不能为空");
        }
        List<Integer> elementId = addRouteRequest.getElementId();
        if (elementId.isEmpty()){
            throw new ServiceException(ErrorCode.PARAMS_ERROR, "路线元素不能为空");
        }


        Gson gson = new Gson();
        String alongScenicsJson = gson.toJson(alongScenics);
        String elementIdJson = gson.toJson(elementId);


        Route route = new Route();
        route.setRouteName(routeName);
        route.setRouteInfo(routeInfo);
        route.setRouteImage(qiniuUtil.upload(routeImage));
        route.setRouteMileage(routeMileage);
        route.setSpendTime(spendTime);
        route.setSuitableTime(suitableTime);
        route.setAlongScenics(alongScenicsJson);
        route.setElementId(elementIdJson);
        route.setUserId(loginUserId);

        //RouteVo routeVo = new RouteVo();
        //BeanUtils.copyProperties(route, routeVo);
        //List<ScenicAreaVo> alongScenicsList = routeVo.getAlongScenics();
        //for (Integer alongScenic : alongScenics) {
        //    //获取单个景区信息
        //    ScenicArea scenicArea = scenicAreaMapper.selectById(alongScenic);
        //    //判断该景区是否存在
        //    if (scenicArea == null) {
        //        return null;
        //    }
        //    //获取该景区下的所有景点
        //    QueryWrapper<ScenicSpot> queryWrapper = new QueryWrapper<>();
        //    queryWrapper.lambda().eq(ScenicSpot::getScenicAreaId, alongScenic);
        //    List<ScenicSpot> scenicSpots = scenicSpotMapper.selectList(queryWrapper);
        //
        //    ScenicAreaVo scenicAreaVo = new ScenicAreaVo();
        //    scenicAreaVo.setSpots(scenicSpots);
        //    BeanUtils.copyProperties(scenicArea, scenicAreaVo);
        //    alongScenicsList.add(scenicAreaVo);
        //}
        //
        //List<Element> elementList = routeVo.getElementId();
        //for (Integer element : elementId) {
        //    Element elementdb = elementMapper.selectById(element);
        //    //判断该元素是否存在
        //    if (elementdb == null) {
        //        return null;
        //    }
        //    elementList.add(elementdb);
        //}
        RouteVo routeVo = getRouteInfo(route);

        int i = routeMapper.insert(route);
        if (i <= 0) {
            throw new ServiceException(ErrorCode.SYSTEM_ERROR);
        }
        routeVo.setId(route.getId());
        routeVo.setStatus(routeMapper.selectById(route.getId()).getStatus());
        return routeVo;

    }

    @Override
    public RouteVo searchRoute(int id, HttpServletRequest request) {
        if (id <= 0){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        UserVo loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            throw new ServiceException(ErrorCode.NOT_LOGIN);
        }

        if (userService.isAdmin(loginUser)){
            //管理员
            Route route = routeMapper.selectById(id);
            return getRouteInfo(route);
        } else {
            //普通用户
            QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(Route::getId, id);
            queryWrapper.lambda().eq(Route::getStatus, UNAPPROVED);
            queryWrapper.lambda().eq(Route::getUserId, loginUser.getUserid());
            Route route = routeMapper.selectOne(queryWrapper);
            return getRouteInfo(route);
        }
    }

    @Override
    public RouteVo getRouteInfo(Route route) {
        if (route == null){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        RouteVo routeVo = new RouteVo();
        String alongScenics = route.getAlongScenics();
        Gson gson = new Gson();
        int[] nums = gson.fromJson(alongScenics, int[].class);
        List<ScenicAreaVo> alongScenicsList = routeVo.getAlongScenics();
        for (int num : nums){
            ScenicArea scenicArea = scenicAreaMapper.selectById(num);
            if (scenicArea == null){
                throw new ServiceException(ErrorCode.PARAMS_ERROR, "存在未知景区");
            }
            ScenicAreaVo scenicAreaVo = new ScenicAreaVo();
            BeanUtils.copyProperties(scenicArea, scenicAreaVo);
            QueryWrapper<ScenicSpot> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ScenicSpot::getScenicAreaId, num);
            scenicAreaVo.setSpots(scenicSpotMapper.selectList(queryWrapper));
            alongScenicsList.add(scenicAreaVo);
        }

        String elementId = route.getElementId();
        int[] elementIds = gson.fromJson(elementId, int[].class);
        List<Element> elementList = routeVo.getElementId();
        for (int elementId1 : elementIds){
            Element element = elementMapper.selectById(elementId1);
            if (element == null){
                throw new ServiceException(ErrorCode.PARAMS_ERROR, "存在未知元素");
            }
            elementList.add(element);
        }
        BeanUtils.copyProperties(route, routeVo);
        return routeVo;
    }

    @Override
    public List<RouteVo> getRouteInfoList(List<Route> routeList) {
        ArrayList<RouteVo> routeVoList = new ArrayList<>();
        if (routeList.isEmpty()){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        for (Route route : routeList){
            if (route == null){
                throw new ServiceException(ErrorCode.PARAMS_ERROR);
            }

            routeVoList.add(getRouteInfo(route));
        }
        return routeVoList;
    }

    @Override
    public RouteVo updateRoute(UpdateRouteRequest updateRouteRequest, HttpServletRequest request) {
        Integer id = updateRouteRequest.getId();
        if (id <= 0){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        UserVo loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            throw new ServiceException(ErrorCode.NOT_LOGIN);
        }
        if (userService.isAdmin(loginUser)){
            //管理员
            QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(Route::getId, id);
            queryWrapper.lambda().eq(Route::getStatus, APPROVE);
            Route routedb = routeMapper.selectOne(queryWrapper);
            return updateRouteInfo(routedb, updateRouteRequest);
        }else {
            //普通用户
            QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(Route::getId, id);
            queryWrapper.lambda().eq(Route::getUserId, loginUser.getUserid());
            queryWrapper.lambda().eq(Route::getStatus, UNAPPROVED);
            Route routedb = routeMapper.selectOne(queryWrapper);
            if (routedb == null){
                throw new ServiceException(ErrorCode.PARAMS_ERROR);
            }
            return updateRouteInfo(routedb, updateRouteRequest);
        }
    }

    @Override
    public RouteVo updateRouteInfo(Route routedb, UpdateRouteRequest updateRouteRequest) {
        Route route = new Route();
        Gson gson = new Gson();
        if (updateRouteRequest.getAlongScenics() != null){
            List<Integer> alongScenics = updateRouteRequest.getAlongScenics();
            for (Integer alongScenic : alongScenics){
                if (scenicAreaMapper.selectById(alongScenic) == null){
                    throw new ServiceException(ErrorCode.PARAMS_ERROR, "存在未知景区");
                }
            }
            route.setAlongScenics(gson.toJson(updateRouteRequest.getAlongScenics()));
        }
        if (updateRouteRequest.getElementId() != null){
            List<Integer> elementIds = updateRouteRequest.getElementId();
            for (Integer elementId : elementIds){
                if (elementMapper.selectById(elementId) == null){
                    throw new ServiceException(ErrorCode.PARAMS_ERROR, "存在未知元素");
                }
            }
            route.setElementId(gson.toJson(updateRouteRequest.getElementId()));
        }

        BeanUtils.copyProperties(updateRouteRequest, route);
        if (updateRouteRequest.getRouteImage() != null){
            qiniuUtil.deleteFile(routedb.getRouteImage());
            route.setRouteImage(qiniuUtil.upload(updateRouteRequest.getRouteImage()));
        }
        //更新
        int i = routeMapper.updateById(route);
        if (i <= 0){
            throw new ServiceException(ErrorCode.SYSTEM_ERROR);
        }
        return getRouteInfo(route);
    }

    @Override
    public int deleteRoute(List<Integer> ids, HttpServletRequest request) {
        if (ids.isEmpty()){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        for (Integer id : ids){
            Route route = routeMapper.selectById(id);
            if (route == null){
                throw new ServiceException(ErrorCode.PARAMS_ERROR);
            }
        }
        UserVo loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            throw new ServiceException(ErrorCode.NOT_LOGIN);
        }
        if (userService.isAdmin(loginUser)){
            //管理员
            int count = 0;
            for (Integer id : ids){
                QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(Route::getId, id);
                //已审核
                //todo 管理员能删除用户发布但未审核的路线吗
                queryWrapper.lambda().eq(Route::getStatus, APPROVE);
                int i = routeMapper.delete(queryWrapper);
                if (i <= 0){
                    throw new ServiceException(ErrorCode.SYSTEM_ERROR);
                }else {
                    count++;
                }
            }
            return count;
        }else {
            //普通用户
            int count = 0;
            for (Integer id : ids){
                QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(Route::getId, id);
                //未审核
                queryWrapper.lambda().eq(Route::getStatus, UNAPPROVED);
                queryWrapper.lambda().eq(Route::getUserId, loginUser.getUserid());
                int i = routeMapper.delete(queryWrapper);
                if (i <= 0){
                    throw new ServiceException(ErrorCode.SYSTEM_ERROR);
                }else {
                    count++;
                }
            }
            return count;
        }
    }

    @Override
    public Boolean auditRoute(int id, HttpServletRequest request) {
        if (id <= 0){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        if (!userService.isAdmin(request)){
            throw new ServiceException(ErrorCode.NO_AUTH);
        }
        Route route = routeMapper.selectById(id);
        if (route == null || !Objects.equals(route.getStatus(), UNAPPROVED)){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        route.setUpdateTime(null);
        route.setStatus(APPROVE);
        int i = routeMapper.updateById(route);
        if (i <= 0){
            throw new ServiceException(ErrorCode.SYSTEM_ERROR);
        }
        return true;
    }

    @Override
    public List<RouteVo> searchRoute(Integer elementId) {
        if (elementId == null || elementId <= 0){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }
        ArrayList<Route> list = new ArrayList<>();
        this.list().forEach(route -> {
            if (route.getElementId() != null){
                Gson gson = new Gson();
                List<Integer> elementIds = gson.fromJson(route.getElementId(), new TypeToken<List<Integer>>(){}.getType());
                if (elementIds.contains(elementId) && route.getStatus().equals(APPROVE)){
                    list.add(route);
                }
            }
        });
        return getRouteInfoList(list);

    }

    @Override
    public RouteVo searchRoute(int id) {
        QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Route::getId, id);
        queryWrapper.lambda().eq(Route::getStatus, APPROVE);
        Route route = this.getOne(queryWrapper);
        if (route == null){
            throw new ServiceException(ErrorCode.PARAMS_ERROR);
        }

        return getRouteInfo(route);
    }

    @Override
    public List<RouteVo> searchRoute(SearchRouteRequest searchRouteRequest) {
        return Collections.emptyList();
    }


    @Override
    public IPage<RouteVo> searchRoute(String routeName, HttpServletRequest request) {
        UserVo loginUser = userService.getLoginUser(request);
        if (loginUser == null){
            throw new ServiceException(ErrorCode.NOT_LOGIN);
        }

        if (userService.isAdmin(loginUser)){
            //管理员
            QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
            if (routeName != null){
                queryWrapper.lambda().like(Route::getRouteName, routeName);
            }
            PageRequest pageRequest = new PageRequest();
            Page<Route> page = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
            Page<Route> routePage = this.page(page, queryWrapper);
            List<RouteVo> routeInfoList = getRouteInfoList(routePage.getRecords());
            Page<RouteVo> routeVoPage = new Page<>(routePage.getCurrent(), routePage.getSize(), routePage.getTotal());
            routeVoPage.setRecords(routeInfoList);
            return routeVoPage;
        }else {
            //普通用户
            QueryWrapper<Route> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(Route::getStatus, UNAPPROVED);
            if (routeName != null){
                queryWrapper.lambda().like(Route::getRouteName, routeName);
            }
            PageRequest pageRequest = new PageRequest();
            Page<Route> page = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
            Page<Route> routePage = this.page(page, queryWrapper);
            List<RouteVo> routeInfoList = getRouteInfoList(routePage.getRecords());
            Page<RouteVo> routeVoPage = new Page<>(routePage.getCurrent(), routePage.getSize(), routePage.getTotal());
            routeVoPage.setRecords(routeInfoList);
            return routeVoPage;
        }
    }
}




